﻿using System;
using System.IO;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Collections.ObjectModel;
using System.Windows.Input;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Documents;
using System.Windows.Shapes;
using System.Windows.Media.Media3D;
using System.Xml;
using System.Collections;
using System.Data;
using System.Diagnostics;
namespace Data
{
  public  class Mesh3D// The same MeshGeometry3d 
    {
        public List<Triangle3D>list_triangle=new List<Triangle3D>();
        public GeometryModel3D geometry = new GeometryModel3D();
        public MeshGeometry3D trianglemesh = new MeshGeometry3D();
                
        //Double zmax, ymax, zmin, ymin, xmax, xmin;
        public Mesh3D() {}
        public ArrayList  GetListPoint()// create point 3d array from mesh.
        {
            ArrayList point= new ArrayList();
            int i=0;
            for(i=0;i<list_triangle.Count;i++)
            {
                point.Add(list_triangle[i].V1);
                point.Add(list_triangle[i].V2);
                point.Add(list_triangle[i].V3);
            }
            return point;
        }
        public Double Zmax()
        {
            Double temp = 0;
            temp = list_triangle[0].Zmax();
            for (int i = 0; i < list_triangle.Count; i++)
            {
                if(temp< list_triangle[i].Zmax())
                     temp = list_triangle[i].Zmax();
            }
            Debug.WriteLine("[MESH3D] Z MAX :" + temp.ToString());
             return temp;
        }
        public Double Zmin()
        {
            Double temp = 0;
            temp = list_triangle[0].Zmin();
            for (int i = 0; i < list_triangle.Count; i++)
            {
                if (temp > list_triangle[i].Zmin())
                    temp = list_triangle[i].Zmin();
            }
            Debug.WriteLine("[MESH3D] Z MIN :" + temp.ToString());
            return temp;
        }
        public Double Ymax()
        {
            Double temp = 0;
            temp = list_triangle[0].Ymax();
            for (int i = 0; i < list_triangle.Count; i++)
            {
                if (temp < list_triangle[i].Ymax())
                    temp = list_triangle[i].Ymax();
            }
            Debug.WriteLine("[MESH3D] Y MAX :" + temp.ToString());
            return temp;
        }
        public Double Ymin()
        {
            Double temp = 0;
            temp = list_triangle[0].Ymin();
            for (int i = 0; i < list_triangle.Count; i++)
            {
                if (temp > list_triangle[i].Ymin())
                    temp = list_triangle[i].Ymin();
            }
            Debug.WriteLine("[MESH3D] Y MIN :" + temp.ToString());
            return temp;
        }
        public Double Xmax()
        {
            Double temp = 0;
            temp = list_triangle[0].Xmax();
            for (int i = 0; i < list_triangle.Count; i++)
            {
                if (temp < list_triangle[i].Xmax())
                    temp = list_triangle[i].Xmax();
            }
            Debug.WriteLine("[MESH3D] X MAX :" + temp.ToString());
            return temp;
        }
        public Double Xmin()
        {
            Double temp = 0;
            temp = list_triangle[0].Xmin();
            for (int i = 0; i < list_triangle.Count; i++)
            {
                if (temp > list_triangle[i].Xmin())
                    temp = list_triangle[i].Xmin();
            }
            Debug.WriteLine("[MESH3D] X MIN :" + temp.ToString());
            return temp;
        }
      public Triangle3D GetTriangle(int i)
      {
            return list_triangle[i];
      }
      public int GetTriangleNumber()
      {
            return list_triangle.Count;
      }
      public void AddItem(Triangle3D tri)
      {
        this.list_triangle.Add(tri);
      }
      public Point3D getCenter()
      {
          Point3D ct = new Point3D(0,0,0);
          Double x, y, z;
          x = y = z=0;
          if (list_triangle.Count == 0)
              return ct;
          for (int i = 0; i < list_triangle.Count; i++)
          {
              x = x + list_triangle[i].Getcenter().X;
              y = y + list_triangle[i].Getcenter().Y;
              z = z + list_triangle[i].Getcenter().Z;
          }
          x = Math.Round( x / list_triangle.Count);
          y = Math.Round( y / list_triangle.Count);
          z = Math.Round( z / list_triangle.Count);
          ct = new Point3D(x,y,z);
          return ct;
      }
      public ModelVisual3D CreateModel3D(Color color)
      {
         
          Model3DGroup mg = new Model3DGroup();

          for (int i = 0; i < this.list_triangle.Count; i++)
          {

              Triangle3D triangle = this.list_triangle[i];
              trianglemesh.Positions.Add(triangle.V1);
              trianglemesh.Positions.Add(triangle.V2);
              trianglemesh.Positions.Add(triangle.V3);
           
          }
          
          SolidColorBrush brush = new SolidColorBrush();
          brush.Color = color;
          Material material = new DiffuseMaterial(brush);
          geometry.Geometry = trianglemesh;
          geometry.Material = material;
          mg.Children.Add(geometry);
          ModelVisual3D md = new ModelVisual3D();
          md.Content = mg;
          return md;
      }
      public Model3DGroup CreateMesh(Color color)
      {
          GeometryModel3D geometry =new GeometryModel3D();
          MeshGeometry3D  trianglemesh=new MeshGeometry3D();
          Model3DGroup mg = new Model3DGroup();

          for (int i = 0; i < this.list_triangle.Count;i++ )
          {

              Triangle3D triangle = this.list_triangle[i];
              trianglemesh.Positions.Add(triangle.V1);
              trianglemesh.Positions.Add(triangle.V2);
              trianglemesh.Positions.Add(triangle.V3);
              trianglemesh.TriangleIndices.Add(0 + 3 * i);
              trianglemesh.TriangleIndices.Add(1 + 3 * i);
              trianglemesh.TriangleIndices.Add(2 + 3 * i);
              trianglemesh.Normals.Add(triangle.Normal);
              trianglemesh.Normals.Add(triangle.Normal);
              trianglemesh.Normals.Add(triangle.Normal);

          }
          SolidColorBrush brush = new SolidColorBrush();
          brush.Color = color;
          Material material = new DiffuseMaterial(brush);
          geometry.Geometry = trianglemesh;
          geometry.Material = material;
          mg.Children.Add(geometry);
          return mg;
      }
      public Mesh3D transform(Matrix3D m)
      {
          Mesh3D mesh = new Mesh3D();
          Triangle3D tri = new Triangle3D();
          Point3D p1 = new Point3D();
          Point3D p2 = new Point3D();
          Point3D p3 = new Point3D();
          Vector3D n=new Vector3D();
          for (int i = 0; i < list_triangle.Count; i++)
          {
              n =Vector3D.Multiply( list_triangle[i].Normal,m);
              p1 = Point3D.Multiply(list_triangle[i].V1,m);
              p2 = Point3D.Multiply(list_triangle[i].V2, m);
              p3 = Point3D.Multiply(list_triangle[i].V3, m);
              tri = new Triangle3D(n, p1, p2, p3);
              mesh.AddItem(tri);
          }
          return mesh;
      }
      public void Transfoms(Matrix3D m)
      { 
          List<Triangle3D>metri=new List<Triangle3D>();
          Triangle3D tri = new Triangle3D();
          Point3D p1 = new Point3D();
          Point3D p2 = new Point3D();
          Point3D p3 = new Point3D();
          Vector3D n=new Vector3D();
          for (int i = 0; i < list_triangle.Count; i++)
          {
              n = Vector3D.Multiply(list_triangle[i].Normal, m);
              p1 = Point3D.Multiply(list_triangle[i].V1, m);
              p2 = Point3D.Multiply(list_triangle[i].V2, m);
              p3 = Point3D.Multiply(list_triangle[i].V3, m);
              tri = new Triangle3D(n, p1, p2, p3);
              metri.Add(tri);
          }
          list_triangle = metri;
      }
    
      public void Calculate()
      {

          int i = 0;
          Vector3D N = new Vector3D(0, 0, 0);
          Point3D p = new Point3D(0, 0, 0);

          Vector3D temp = new Vector3D(0, 0, 0);
          for (i = 0;i < trianglemesh.Positions.Count;i++ )
          {


              N = new Vector3D(0,0,0);
              p = new Point3D(trianglemesh.Positions[i].X, trianglemesh.Positions[i].Y, trianglemesh.Positions[i].Z);
              
              for(int j=0;j < list_triangle.Count;j++)
              {
                                         
                  if (list_triangle[j].CheckShared(p))
                  {
                      temp = list_triangle[j].CalculateNormal();
                      temp.Normalize();
                      N = Vector3D.Add(temp,N);
                  }
                    
                  

              }
              N.Normalize();
              trianglemesh.Normals.Add(N);
             

          }
          MessageBox.Show(i.ToString());

      }
      public void CalculateNormal()
      {

          int i = 0;
          Vector3D n1 = new Vector3D(0, 0, 0);
          Vector3D n2 = new Vector3D(0, 0, 0);
          Vector3D n3 = new Vector3D(0, 0, 0);
          Vector3D tem = new Vector3D(0, 0, 0);
          ArrayList a = new ArrayList();
          for (i = 0; i < list_triangle.Count; i++)
          {
              n1 = Vector3D.Add(n1, list_triangle[i].CalculateNormal());
              n2 = Vector3D.Add(n2, list_triangle[i].CalculateNormal());
              n3 = Vector3D.Add(n3, list_triangle[i].CalculateNormal());
              n1.Normalize(); n2.Normalize(); n3.Normalize();
              a.Add(n1); a.Add(n2); a.Add(n3);
             
          }
          for (i = 0; i < a.Count; i++)
              trianglemesh.Normals.Add((Vector3D)a[i]);
          

      }

    }
}
